﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
using DotSpatial.Map;
using DotSpatial.Data;
using DotSpatial.Geometries;
using DotSpatial.Drawing;
using Point = System.Drawing.Point;
using DotSpatial.Main;

namespace HuanGis.selDefMapFunctions
{
    /// <summary>
    /// 自定义的选择函数
    /// </summary>
    class SelectShapeMF : FMapFunctionBase 
    {

        # region 构造函数

        public SelectShapeMF()
        {
            Configure();
        }

        public SelectShapeMF(IMap map)
            : base(map)
        {
            Configure();
        }

        public void Configure()
        {
        
        }
        
        # endregion


        # region 字段

        private bool _dragging;
        private Point _mousePosition;
        private List<IFeature> _activeFeature;
        private List<IFeature> _selectedFeature;               
        private IFeatureLayer _layer;  //当前图层
        private IFeatureSet _featureSet;
        private IFeatureCategory _oldCategory;
        private IFeatureCategory _selectedCategory;
        private IFeatureCategory _activeCategory;
        private  Point  _dragCoord;


        # endregion

        # region 属性

        public IFeatureLayer Layer
        {
            get { return _layer; }
            set
            {
                _layer = value;
                _featureSet = _layer.DataSet;

            }
        }

        public List<IFeature> SelectedFeature
        {
            get { return _selectedFeature; }
            set { _selectedFeature = value; }
        }



        # endregion




        # region 方法


        protected override void OnDraw(MapDrawArgs e)
        {
            if (_dragging == false) return;
            if (_dragCoord == null) return;

            e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
            Rectangle SelectRect=new Rectangle (Math.Min(_dragCoord.X, _mousePosition.X), Math.Min(_dragCoord.Y, _mousePosition.Y), Math.Abs(_mousePosition.X - _dragCoord.X), Math.Abs(_dragCoord.Y - _mousePosition.Y));

            e.Graphics.DrawRectangle(Pens.Red, SelectRect);

            base.OnDraw(e);
        
        
        }




        /// <summary>
        /// 使鼠标经过的和选中的Shape亮起来
        /// </summary>
        /// <param name="e"></param>
        /// <returns></returns>
        private bool ShapeHighlight()
        {
            
            Rectangle SelectRect = new Rectangle(Math.Min(_dragCoord.X, _mousePosition.X), Math.Min(_dragCoord.Y, _mousePosition.Y), Math.Abs(_mousePosition.X - _dragCoord.X), Math.Abs(_mousePosition.Y - _dragCoord.Y));
            IEnvelope ext = Map.PixelToProj(SelectRect);
            IPolygon env = ext.ToPolygon();           

            bool requiresInvalidate = false;

            foreach (IFeature feature in _featureSet.Features)
            {
                if (_featureSet.FeatureType == FeatureTypes.Point)
                {
                    MapPointLayer mpl = _layer as MapPointLayer;

                    if (mpl != null)
                    {
                       

                        if (SelectRect.Contains(Map.ProjToPixel(feature.Coordinates[0])))  //本句判断是不是选择的这个Feature，以下代码用来表现选择的Feature
                        {
                            _activeFeature.Add(feature); 
                            _oldCategory = mpl.GetCategory(feature);

                            if (_selectedCategory == null)
                            {
                                _selectedCategory=_oldCategory;  //这一句不一样，怎么相同的控件方法还不一样？？？？
                                _selectedCategory.SetColor(Color.Red);
                                _selectedCategory.LegendItemVisible = false;
                            }
                            mpl.SetCategory(_activeFeature[_activeFeature.Count - 1], _selectedCategory);  //选中Feature后，改变一下类型
                        }
                    }
                    requiresInvalidate = true;
                }
                else
                {
                    if (feature.Intersects(env))  //本句判断是不是选择的这个Feature，以下代码只是用来表现此Feature与其它Feature的不同
                    {
                        _activeFeature.Add(feature);
                        _oldCategory = _layer.GetCategory(_activeFeature[_activeFeature.Count - 1]);

                        if (_featureSet.FeatureType == FeatureTypes.Polygon)
                        {
                            PolygonCategory pc = _activeCategory as PolygonCategory;
                            if (pc == null)
                            {
                                _activeCategory = new PolygonCategory(Color.FromArgb(55, 255, 0, 0), Color.Red, 1);
                                _activeCategory.LegendItemVisible = false;
                            
                            }
                        
                        }
                        if (_featureSet.FeatureType == FeatureTypes.Line)
                        {
                            LineCategory pc = _activeCategory as LineCategory;
                            if (pc == null)
                            {
                                _activeCategory = new LineCategory(Color.Red, 3);
                                _activeCategory.LegendItemVisible = false;

                            }                        
                        }

                        _layer.SetCategory(_activeFeature[_activeFeature.Count - 1], _activeCategory);     //这个_activeCategory与_selectedCategory作用一样，类型一样，为什么要写成两个？？？？                    
                   
                    }
                                
                }            
            
            }

            return requiresInvalidate;        

        }


        /// <summary>
        /// 鼠标离开Shape后，Shap要恢复正常
        /// </summary>
        /// <param name="e"></param>
        /// <returns></returns>
        public void ShapeRemoveHighlight()
        {
            if (_selectedFeature == null || _selectedFeature.Count == 0) return; //没有Shape被点亮


            //有Shape被点亮，则将点亮的Shape赋回原来的类型

            //bool requiresInvalidate = false;

            foreach (Feature f in _activeFeature)
            {
                _layer.SetCategory(f, _oldCategory);
                //requiresInvalidate = true;
            }

            _activeFeature.Clear();
            _selectedFeature.Clear();

            Map.MapFrame.Initialize();
            Map.Invalidate();
           
        }

                

        protected override void OnMouseMove(GeoMouseArgs e)
        {
            _mousePosition = e.Location;

            Rectangle invilid = new Rectangle(Math.Min(_dragCoord.X, _mousePosition.X), Math.Min(_dragCoord.Y, _mousePosition.Y), Math.Abs(_mousePosition.X - _dragCoord.X), Math.Abs(_dragCoord.Y - _mousePosition.Y));
            invilid.Inflate(20, 20);
            Map.Invalidate(invilid);

            base.OnMouseMove(e);
                     
        }

        protected override void OnMouseDown(GeoMouseArgs e)
        {

            Map.MapFrame.Initialize();
            Map.Invalidate();

            if (_selectedFeature != null && _selectedFeature.Count >0)  //要先将原来选中的Feature赋回原来的类型
            {
                for (int i = 0; i < _activeFeature.Count; i++)
                    _layer.SetCategory(_activeFeature[i], _oldCategory);
            }



            _dragging = true;
            _activeFeature = new List<IFeature>();
            _selectedFeature = new List<IFeature>();
            _dragCoord = e.Location;
                                  
        }


        protected override void OnMouseUp(GeoMouseArgs e)
        {

            _dragging = false;
           
            this.ShapeHighlight();  //点亮选中的Shape

            foreach (Feature f in _activeFeature)
                _selectedFeature.Add(f);

            Map.MapFrame.Initialize();
                
        }


        
        # endregion




    }
}
